use rkyv::{Archive, Deserialize, Serialize};

use farmfe_macro_cache_item::cache_item;

use crate::module::ModuleId;

use self::resource_pot::ResourcePotId;

pub mod resource_pot;
pub mod resource_pot_map;

#[cache_item]
#[derive(Debug, Clone)]
pub enum ResourceType {
  Runtime,
  Js,
  Css,
  Html,
  SourceMap(String),
  Asset(String),
  Custom(String),
}

impl ResourceType {
  pub fn to_ext(&self) -> String {
    match self {
      ResourceType::Asset(str) => str.to_string(),
      ResourceType::Custom(str) => str.to_string(),
      ResourceType::Runtime => "js".to_string(),
      ResourceType::Js => "js".to_string(),
      ResourceType::Css => "css".to_string(),
      ResourceType::Html => "html".to_string(),
      ResourceType::SourceMap(_) => "map".to_string(),
    }
  }

  pub fn to_html_tag(&self) -> String {
    match self {
      ResourceType::Asset(str) => str.to_string(),
      ResourceType::Custom(str) => str.to_string(),
      ResourceType::Runtime => "script".to_string(),
      ResourceType::Js => "script".to_string(),
      ResourceType::Css => "link".to_string(),
      ResourceType::Html => "html".to_string(),
      ResourceType::SourceMap(_) => unreachable!(),
    }
  }
}

#[cache_item]
#[derive(Debug)]
pub enum ResourceOrigin {
  // The resource is generated by a Resource Pot.
  ResourcePot(ResourcePotId),
  // The resource is generated by a Module. Usually by static assets like images.
  Module(ModuleId),
}

impl ResourceOrigin {
  pub fn as_resource_pot(&self) -> &ResourcePotId {
    match self {
      ResourceOrigin::ResourcePot(id) => id,
      ResourceOrigin::Module(_) => panic!("ResourceOrigin is not ResourceOrigin::ResourcePot"),
    }
  }

  pub fn as_module(&self) -> &ModuleId {
    match self {
      ResourceOrigin::ResourcePot(_) => panic!("ResourceOrigin is not ResourceOrigin::Module"),
      ResourceOrigin::Module(id) => id,
    }
  }
}

#[cache_item]
pub struct Resource {
  pub name: String,
  pub bytes: Vec<u8>,
  /// whether this resource emitted, true means this resource will not present in the final production
  pub emitted: bool,
  pub resource_type: ResourceType,
  /// the origin that this resource generated from
  pub origin: ResourceOrigin,
}
